package tech.yunland.shop.domain.service;

import com.moyuer.bsf.domain.model.HqlArgs;
import com.moyuer.bsf.domain.model.Organ;
import com.moyuer.bsf.domain.service.LogService;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.yunland.shop.domain.dao.*;
import tech.yunland.shop.domain.model.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

/**
 * 调拨单业务层实现类
 * Created by v on 17-5-18.
 */
@Service
public class AllotBillServiceImpl implements AllotBillSevice {

    @Autowired
    private GoodsDao goodsDao;

    @Autowired
    private AllotBillDaoImpl allotBillDao;

    @Autowired
    private AllotBillEntryDaoImpl allotBillEntryDao;

    @Autowired
    protected LogService logService;

    @Autowired
    private SNGenerator snGenerator;

    @Autowired
    private StoreBillService storeBillService;

    @Autowired
    private StoreBillDao storeBillDao;


    @Override
    public Integer getAllAllotBillSize(String param, List<String> organIds, List<Integer> states) {
        if (states != null && states.size() <= 0) {
            throw new RuntimeException("不正确的状态值");
        }
        String strOrginIds = StringUtils.join(organIds, "','");
        String strStates = StringUtils.join(states, ",");
        String sql =
                "select count(1) as counts\n" +
                "from\n" +
                "  allot_bill ab\n" +
                "\n" +
                "where\n" +
                "\n" +
                "      ab.organ_id in('" + strOrginIds + "')\n" +
                "  and ab.state in(" + strStates + ") \n";
        sql += this.getSearchSql(param);
        int counts = ((BigInteger) allotBillDao.findUniqueBySQL(sql).get("counts")).intValue();
        return counts;
    }


    private String getSearchSql(String param) {
        String sql = "";
        if (StringUtils.isNotBlank(param)) {
            sql = "\n   and ab.sn like '%" + param + "%'";
        }
        return sql;
    }

    @Override
    public List<Map<String, Object>> getAllAllotBill(String param, List<String> organIds, List<Integer> states, Integer startIdx, Integer rows) {
        if (states != null && states.size() <= 0) {
            throw new RuntimeException("不正确的状态值");
        }
        String strOrginIds = StringUtils.join(organIds, "','");
        String strStates = StringUtils.join(states, ",");
        String sql =
                "select ab.sn\n" +
                        "      ,bu.name cname\n" +
                        "      ,ab.id\n" +
                        "      ,outstore.name outstorename\n" +
                        "      ,instore.name istorename\n" +
                        "      ,ab.state\n" +
                        "      ,organ.name  oname\n" +
                        "      ,outstore.id outstoreid\n" +
                        "      ,instore.id  instoreid\n" +
                        "      ,ab.handername\n" +
                        "      ,to_char(ab.create_time,'yyyy-MM-dd hh:mm:ss') ctime\n" +
                        "      ,ab.remark remark\n" +
                        "      ,bu.name creator_name\n" +
                        "from\n" +
                        "  allot_bill ab\n" +
                        " ,bsf_organ outstore\n" +
                        " ,bsf_organ instore\n" +
                        " ,bsf_organ organ\n" +
                        " ,bsf_users bu\n" +
                        "where\n" +
                        "    ab.instore_id = instore.id\n" +
                        "and ab.creator_id = bu.id\n" +
                        "and ab.outstore_id = outstore.id\n" +
                        "and ab.organ_id = organ.id\n" +
                        "and ab.organ_id in('" + strOrginIds + "')\n" +
                        "and ab.state in(" + strStates + ")\n";

        sql += this.getSearchSql(param);
        sql += "\n ORDER BY ab.create_time desc";
        List<Map<String, Object>> records = allotBillDao.findBySQL(sql, startIdx, rows);
        return records;


    }

    /**
     * 生成调拨单
     * 此时为暂存状态所以并没有同步生成
     *
     * @param allotBill
     */
    @Override
    public void saveAllotBill(AllotBill allotBill) {
        //给单据绑定状态 刚生成是的状态 生效
        allotBill.setState(0);
        //保存单据
        allotBillDao.saveOrUpdate(allotBill);
        //保存分录
        for (AllotBillEntry entry : allotBill.getEntries()) {
            String goodsId = entry.getGoodsId();

            Goods goods = goodsDao.get(goodsId);

            if (goods == null) {
                throw new RuntimeException("选择商品异常：【您未选择商品或一次性选择多个商品】");
            }

            if (goods.getKindCode().intValue() != 10) {
                throw new RuntimeException(goods.getName() + "为非实物不能保存");
            }

            BigDecimal goodsPrice = goods.getPrice();
            BigDecimal quantity = entry.getQuantity();
            if (quantity.intValue() <= 0) {
                throw new RuntimeException("商品数量应至少为1");
            }
            AllotBillEntry allotBillEntry = new AllotBillEntry();
            allotBillEntry.setGoods(goods);
            allotBillEntry.setQuantity(quantity);
            BigDecimal amount = goodsPrice.multiply(quantity);
            BigDecimal _amount = quantity.multiply(entry.getAllotPrice());
            allotBillEntry.setAmount(_amount);
            allotBillEntry.setPrice(goodsPrice);
            allotBillEntry.setState(Integer.valueOf(1));
            allotBillEntry.setOwner(allotBill);
            allotBillEntry.setAllotPrice(entry.getAllotPrice());
            allotBillEntryDao.save(allotBillEntry);
        }
        StoreBill storeBill = createStoreBill(allotBill);

    }

    @Override
    public void updateAllotBill(String id) {
//        //通过id取到调拨单
//        AllotBill allotBill = allotBillDao.get(id);
//        //判断调拨单存在且尚未执行
//        if (allotBill != null && allotBill.getBiz_type() != 1) {
//
//            //生成出库单 调拨出库 或者入库单 调拨入库
//            StoreBill storeBill = createStoreBill(allotBill);
//            storeBillService.saveStore(storeBill);
//
////            //判读调拨单要执行的操作
////            if (allotBill.getStock_type() == 1) {
////                //保存日志
////                logService.saveLog("调拨单：[" + allotBill.getSn() + "] 完成调入，入库单：[" + storeBill.getSn() + "] 自动生成。", storeBill.getCreator());
////            }
////            if (allotBill.getStock_type() == 0) {
////                //保存日志
////                logService.saveLog("调拨单：[" + allotBill.getSn() + "] 完成调出，出库单：[" + storeBill.getSn() + "] 自动生成。", storeBill.getCreator());
////            }
//
//            //给单据绑定状态 已完成调拨
//           // allotBill.setBiz_type(1);
//            //保存单据
//            allotBillDao.saveOrUpdate(allotBill);
//
//        } else {
//            throw new RuntimeException("调拨单不存在或者此调拨单已完成调拨");
//        }
    }

    /**
     * 生成入库单或者出库单
     *
     * @param allotBill
     */
    private StoreBill createStoreBill(AllotBill allotBill) {

        StoreBill storeBill = new StoreBill();//出库
        StoreBill inBill = new StoreBill();//入库
        storeBill.setCreator(allotBill.getCreator());
        inBill.setCreator(allotBill.getCreator());
        storeBill.setSn(snGenerator.gen("sale", allotBill.getOrganId()));
        storeBill.setOrgan(allotBill.getOrgan());
        storeBill.setCreator(allotBill.getCreator());
        storeBill.setState(Integer.valueOf(0));    //设置状态为生效状态
        /**
         * 调拨单有一个出库和入库
         * 1 先创建出库单据
         * 2 再创建入库单据
         */
        Organ outStore = allotBill.getOutStore();  //出库仓库
        storeBill.setDirection(Integer.valueOf(-1));//出库
        storeBill.setBiz_type(Integer.valueOf(-3)); //调拨出库
        storeBill.setOrgan(outStore);             //设置该单据的出库仓库
        storeBill.setRemark(allotBill.getRemark());

        /**
         * 开始入库操作
         */
        Organ inStore = allotBill.getInStore();
        inBill.setDirection(Integer.valueOf(1));//入库
        inBill.setBiz_type(Integer.valueOf(3)); //调拨入库
        inBill.setOrgan(inStore);             //设置该单据的入库仓库
        inBill.setRemark(allotBill.getRemark());
        HashSet<StoreBillEntry> storeBillEntries = new HashSet<>();
        Set<AllotBillEntry> entries = allotBill.getEntries();
        for (AllotBillEntry entry : entries) {
            //过滤标记删除的分类
            if (entry.getState().intValue() != -1) {
                StoreBillEntry storeBillEntry = new StoreBillEntry();
                storeBillEntry.setQuantity(entry.getQuantity());
                storeBillEntry.setGoods(entry.getGoods());
                storeBillEntry.setOwner(storeBill);
                storeBillEntry.setState(Integer.valueOf(0));
                storeBillEntries.add(storeBillEntry);
            }
        }

        storeBill.setEntries(storeBillEntries);
        inBill.setEntries(storeBillEntries);
        String insn = snGenerator.gen("sale", allotBill.getInStoreId());
        String outsn = snGenerator.gen("sale", allotBill.getOutStoreId());
        storeBill.setSn(outsn);
        inBill.setSn(insn);

        storeBill.setBizBillId(allotBill.getId());
        inBill.setBizBillId(allotBill.getId());

        storeBill.setBizBillSn(allotBill.getSn());
        inBill.setBizBillSn(allotBill.getSn());

        storeBill.setHanderName(allotBill.getHanderName());
        inBill.setHanderName(allotBill.getHanderName());
        storeBillService.saveStore(storeBill);//保存出库
        storeBillService.saveStore(inBill);//保存入库

        return storeBill;
    }

    private HqlArgs getAllotBillHqlArgs(String param, String organId, List<Integer> states) {

        param = StringUtils.trimToEmpty(param);
        Map<String, Object> args = new HashMap<>();
        String hql = "FROM AllotBill a WHERE a.entries.size>0 AND EXISTS (SELECT e.id FROM a.entries e WHERE e.state=1)";

        if (states != null && states.size() > 0) {
            if (states.size() == 1) {
                hql += " AND a.state = :state";
                args.put("state", states.get(0));
            } else {
                hql += " AND a.state IN :states";
                args.put("states", states);
            }
        } else {
            hql += " AND a.state <> -1";
        }

        if (StringUtils.isNotBlank(StringUtils.trimToEmpty(organId))) {
            hql += " AND a.organ.id = :organId";
            args.put("organId", organId);
        }

//        if (biztype != null) {
//            hql += " AND a.biz_type = :biz_type";
//            args.put("biz_type", biztype);
//        }
        if (states != null && states.size() > 0) {
            String statesStr = StringUtils.join(states, ",");
            hql += " and a.state in  :states";
            args.put("states", states);
        }
        if (StringUtils.isNotBlank(param)) {
            //  hql += " AND (a.sn LIKE :param OR a.remark LIKE :param OR (CASE biz_type WHEN '0' THEN '未调拨' WHEN '1' THEN '已调拨' END) LIKE :param OR";
//            hql += " (CASE p.state WHEN '0' THEN '暂存' WHEN '-2' THEN '未通过' WHEN '1' THEN '审批中' WHEN '2' THEN '通过' END) LIKE :param OR";
            hql += "and  a.creator.name LIKE :param OR";
            hql += " EXISTS (SELECT e.id FROM a.entries e WHERE e.state=1 AND (e.goods.name LIKE :param OR e.goods.spell LIKE :param)))";
            args.put("param", "%" + param + "%");
        }


        return new HqlArgs(hql, args);
    }

    public List<AllotBillEntry> getEntryList(String ownerId, Integer startIndex, Integer row) {
        String hql = "FROM AllotBillEntry ae WHERE 1=1 AND ae.owner.id = ? ORDER BY ae.createTime DESC";
        List<AllotBillEntry> allotBillEntries = this.allotBillEntryDao.find(hql, startIndex, row, ownerId);
        return allotBillEntries;
    }

    public long getEntryListSize(String ownerId) {
        String hql = "FROM AllotBillEntry ae WHERE 1=1 AND ae.owner.id = :ownerId";
        HashMap<String, Object> args = new HashMap<>();
        args.put("ownerId", ownerId);
        long count = this.allotBillEntryDao.getCount(hql, args);
        return count;
    }

    /**
     * 修改调拨单备注
     *
     * @param id
     * @param remark
     */
    public void updateRemark(String id, String remark) {

        String sql = "UPDATE allot_bill SET remark = ? ,ver = ver+1 WHERE id = ?";

        Session session = this.allotBillEntryDao.getSession();
        SQLQuery query = session.createSQLQuery(sql);
        query.setString(0,remark);
        query.setString(1,id);
        query.executeUpdate();
    }


    /**
     * 修改调拨单状态
     *
     * @param id
     * @param state
     */
    public void updateState(String id, Integer state) {

        String sql = "UPDATE allot_bill SET state = ? ,ver = ver+1 WHERE id = ?";

        Session session = this.allotBillEntryDao.getSession();
        SQLQuery query = session.createSQLQuery(sql);
        query.setInteger(0,state);
        query.setString(1,id);
        query.executeUpdate();
    }
}
